package StreamStudy.Exa03;

import ReflectStudy.util.ProxyTest;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 重点的重点，建议工作中经常去使用
 * 学习流的转换:
 * 涉及API: filter() 条件过滤 ,map() 结果转换 ,flatMap() 单子转换
 * limit() 裁剪 ，skip() 跳跃裁剪 ，concat（）连接流 ，distinct() 去重
 * sorted() 排序 ， peek() 方便查看流处理进度
 */
public class StreamChange {

    private static String[] words = {"hello", "world", "change", "self", "result","result"};

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        String functionName = "peek";
        testProxy(functionName);
    }

    /**
     * 测试代理类,根据名称路由到具体的方法执行
     * @param functionName
     */
    public static void testProxy(String functionName)
            throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        System.out.println("words 内容入下: "+Arrays.asList(words));
        ProxyTest.invoke(StreamChange.class,functionName);
    }

    /**
     * 流的过滤 filter学习
     * @param
     */
    public void filter() {
        Stream<String> wordsStream = Stream.of(words);
        //通过filter方法筛选出元素长度大于4的元素集的流
        Stream<String> filterWords = wordsStream.filter(s->{
            return s.length()>4;
        });
        System.out.println("words数组中元素长度大于4的个数有: "+ filterWords.count());
    }

    /**
     * 流的内容转换 map 学习
     */
    public static void map() {
        Stream<String> wordsStream = Stream.of(words);
        // wordsStream的String转换为Integer
        Stream<Integer> wordsLength = wordsStream.map(s->{
            return s.length();
        });
       // 验证结果
        List<Integer> result = wordsLength.collect(Collectors.toList());
        System.out.println("map转换将 words 内容转换为长度数组： "+result);
    }

    /**
     * 扁平化转换
     */
    public static void flatMap() {
        Stream<String> stringStream = Stream.of(words);
        Stream<String> stream = stringStream.flatMap(s->{
           List<String> result = new ArrayList<>();
           result.add(s.charAt(0)+"");
           return result.stream();
        });
        List<String> result = stream.collect(Collectors.toList());
        System.out.println("将words 进行扁平化处理后的结果为："+ result);
    }

    /**
     * 流的裁剪
     */
    public static void limit() {
        Stream<String> wordsStream = Stream.of(words);
        Stream<String> limitWords = wordsStream.limit(3);
        List<String> limit3Words = limitWords.collect(Collectors.toList());
        System.out.println("通过limit方法取words的前三位元素： " + limit3Words);
    }


    /**
     * 流的跳跃
     */
    public static void skip() {
        Stream<String> wordsStream = Stream.of(words);
        Stream<String> skip3 = wordsStream.skip(3);
        List<String> result = skip3.collect(Collectors.toList());
        System.out.println("通过skip方法跳过前面的三个元素："+result);
    }


    /**
     * 流的合并
     */
    public static void concat() {
        Stream<String> wordsStream = Stream.of(words);
        String[] words2 = {"hello","words","concat"};
        System.out.println("words2: "+ Arrays.asList(words2));
        Stream<String> words2Stream = Stream.of(words2);
        Stream<String> concatWords = Stream.concat(wordsStream,words2Stream);
        List<String> result = concatWords.collect(Collectors.toList());
        System.out.println("通过concat方法将words 和words2进行合并： "+result);
    }

    /**
     * 去重流中元素
     */
    public static void distinct() {
        Stream<String> wordsStream = Stream.of(words);
        Stream<String> distinctStream = wordsStream.distinct();
        List<String> result = distinctStream.collect(Collectors.toList());
        System.out.println("通过distinct方法将words的重复的元素去掉： "+result);
    }

    /**
     * 流中元素的排序
     */
    public static void sorted() {
        Stream<String> wordsStream = Stream.of(words);
        Stream<String> sortedStream = wordsStream.sorted((o1,o2)->{
            //排序规则
            return o1.length()-o2.length();
        });
        List<String> result = sortedStream.collect(Collectors.toList());
        System.out.println("words通过长度排序后的结果为： "+result);
    }

    public static void peek() {
        Stream<String> wordStream = Stream.of(words);
        Stream<String> peekStream = wordStream.peek(s->{
            System.out.println("取出元素+"+s);
        });
        List<String> result = peekStream.collect(Collectors.toList());
        System.out.println(result);
    }

    /**
     * stream场景练习题：
     * 通过流获取一个字符串列表的所有平摊元素数组
     * 例如给定一个数组：{"word","hello"}
     * 希望获得结果：{'w','o','r','d','h','e','l','l','o'}
     *
     * 一般解决思路：
     * 1.在外面新建一个结果容器，在forEach过程中进行处理存入
     * 2.通过flatMap将元素处理完后组成流集合，然后直接调用结果函数得到结果集
     */
    public static void streamDemo1() {
        Stream<String> stream = Stream.of(words);
        //方法一
        List<String> result = new ArrayList<>();
        stream.forEach(s->{
            for(char n: s.toCharArray()) {
                result.add(""+n);
            }
        });
        System.out.println(result);
        // 方法二，使用flatMap处理, flatMap可以将元素通过自定义方式转化为stream,flatMap不常用
        List<String> restrs = Stream.of(words).flatMap(w->letters(w)).collect(Collectors.toList());
        System.out.println(restrs);

    }


    /**
     * 此方法的作用是将字符串中的各个字符拆分开来存入流中
     * @param s 字符串
     * @return 包含字符串字符的流
     */
    public static Stream<String> letters(String s) {
        List<String> result=new ArrayList<>();
        for(int i=0;i<s.length();i++){
            result.add(s.substring(i,i+1));
        }
        return result.stream();
    }

}
